home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- /* convert a pathname to an absolute one, if it is absolute already,
- it is returned in the buffer unchanged, otherwise leading "./"s
- will be removed, and "../"s will be resolved.
-
- In a moment of weakness, I have implemented the cshell ~ filename
- convention. ~/foobar will have the ~ replaced by the home directory of
- the current user. ~user/foobar will have the ~user replaced by the
- home directory of the named user. This should really be in the kernel
- (or be replaced by a better kernel mechanism). Doing file name
- expansion like this in a user-level program leads to some very
- distasteful non-uniformities.
-
- Another fit of dementia has led me to implement the expansion of shell
- environment variables. $HOME/mbox is the same as ~/mbox. If the
- environment variable a = "foo" and b = "bar" then:
- $a => foo
- $a$b => foobar
- $a.c => foo.c
- xxx$a => xxxfoo
- ${a}! => foo!
-
- James Gosling @ CMU
- */
-
- /* #include <sys/types.h>
- #include <sys/stat.h> */
- #include <pwd.h>
- #include "ctype.h"
-
- expand_path (nm, buf) /* input name in nm, absolute pathname
- output to buf. returns 0 on success
- -1 on failure with error msg in buf */
- char *nm,
- * buf; {
- register char *s,
- *d;
- char lnm[1000];
- s = nm;
- d = lnm;
- while (*d++ = *s)
- if (*s++ == '$') {
- register char *start = d;
- register braces = *s == '{';
- register char *value;
- while (*d++ = *s)
- if (braces ? *s == '}' : !(isalpha(*s) || isdigit(*s)
- || (*s == '_')))
- break;
- else
- s++;
- *--d = 0;
- value = (char *) getenv (braces ? start + 1 : start);
- if (value) {
- for (d = start - 1; *d++ = *value++;);
- d--;
- if (braces && *s)
- s++;
- }
- }
- d = buf;
- nm = lnm;
- if (nm[0] == '~') /* prefix ~ */
- if (nm[1] == '/' || nm[1] == 0)/* ~/filename */
- if (s = (char *) getenv ("HOME")) {
- if (*++nm)
- nm++;
- }
- else
- s = "";
- else { /* ~user/filename */
- register char *nnm;
- register struct passwd *pw;
- for (s = nm; *s && *s != '/'; s++);
- nnm = *s ? s + 1 : s;
- *s = 0;
- pw = (struct passwd *) getpwnam (nm + 1);
- if (pw == 0) {
- sprintf (buf,"\"%s\" isn't a registered user.", nm+1);
- return -1;
- }
- else {
- nm = nnm;
- s = pw -> pw_dir;
- }
- }
- while (*d++ = *s++);
- if (buf[0] != '\0') *(d - 1) = '/'; else d--;
- s = nm;
- while (*d++ = *s++);
- *(d - 1) = '/';
- *d = '\0';
- d = buf;
- s = buf;
- while (*s)
- if ((*d++ = *s++) == '/' && d > buf + 1) {
- register char *t = d - 2;
- switch (*t) {
- case '/': /* found // in the name */
- --d;
- break;
- case '.':
- switch (*--t) {
- case '/': /* found /./ in the name */
- d -= 2;
- break;
- #if 0
- case '.':
- if (*--t == '/') {/* found /../ */
- while (t > buf && *--t != '/');
- d = t + 1;
- }
- break;
- #endif
- }
- break;
- }
- }
- if (*(d - 1) == '/')
- d--;
- *d = '\0';
- return 0;
- }
-